<?php

namespace iBrand\Shop\Backend\Http\Controllers;

use Encore\Admin\Facades\Admin as LaravelAdmin;
use Encore\Admin\Layout\Content;
use iBrand\Component\Goods\Models\Goods;
use iBrand\Component\Goods\Models\GoodsCategory;
use iBrand\Component\Goods\Models\GoodsProduct;
use iBrand\Component\Goods\Models\Season;
use iBrand\Component\Goods\Models\SpecsValue;
use iBrand\Component\Goods\Models\Style;
use iBrand\Component\Order\Models\Order;
use iBrand\Shop\Backend\Service\CommonService;
use iBrand\Shop\Backend\Service\SalesReportService;
use iBrand\Shop\Core\Models\ShopOrder;

class SalesReportController extends Controller
{
    protected $commonService;
    protected $salesReportService;
    protected $cache;

    public function __construct(CommonService $commonService, SalesReportService $salesReportService)
    {
        $this->commonService = $commonService;
        $this->salesReportService = $salesReportService;
        $this->cache = cache();
    }

    /**
     * 销售报表
     *
     * @return \Encore\Admin\Layout\Content
     */
    public function index()
    {
        $brandList = $this->commonService->getBrandList();
        $years = $this->commonService->getYearList();
        $categoryList = $this->commonService->getCategoryList();
        $clerks = $this->commonService->getClerkList();
        $specList = $this->commonService->getSpecList();
        $categories = $categoryList['categories'];
        $allCategories = $categoryList['allCategories'];
        $seasons = Season::all()->toArray();
        $styles = Style::all()->toArray();
        $colors = $specList['colors'];
        $sizes = $specList['sizes'];

        return LaravelAdmin::content(function (Content $content) use ($brandList, $years, $clerks, $categories, $allCategories, $seasons, $styles, $colors, $sizes) {

            $content->header('销售报表');

            $content->breadcrumb(
                ['text' => '报表', 'url' => 'warehouse/report/purchase', 'no-pjax' => 1],
                ['text' => '销售报表', 'url' => '', 'no-pjax' => 1, 'left-menu-active' => '销售报表']

            );

            $content->body(view('shop-backend::sales.index', compact('brandList', 'years', 'clerks', 'categories', 'allCategories', 'seasons', 'styles', 'colors', 'sizes')));
        });
    }

    public function saleDetailList()
    {
        $condition = $this->searchCondition();
        $where = $condition[0];
        $time = $condition[1];
        $goods_ids = $condition[2];
        $product_ids = $condition[3];

        if ($goods_ids === [0]) {
            $product_ids = [0];
        } elseif (!empty($goods_ids) && $goods_ids !== [0]) {
            $tmp_ids = GoodsProduct::whereIn('goods_id', $goods_ids)->pluck('id')->all();
            if (!empty($product_ids)) {
                $product_ids = array_intersect($product_ids, $tmp_ids);
            } else {
                $product_ids = $tmp_ids;
            }
        }

        $where['channel_id'] = $where['shop_id'];
        unset($where['shop_id']);

        $list = $this->salesReportService->getSaleDetailList($where, $time, $product_ids);

        return $list->toJson();
    }

    public function saleGroupBySkuList()
    {
        $condition = $this->searchCondition();
        $where = $condition[0];
        $time = $condition[1];
        $goods_ids = $condition[2];
        $product_ids = $condition[3];

        if ($goods_ids === [0]) {
            $product_ids = [0];
        } elseif (!empty($goods_ids) && $goods_ids !== [0]) {
            $tmp_ids = GoodsProduct::whereIn('goods_id', $goods_ids)->pluck('id')->all();
            if (!empty($product_ids)) {
                $product_ids = array_intersect($product_ids, $tmp_ids);
            } else {
                $product_ids = $tmp_ids;
            }
        }

        $where['channel_id'] = $where['shop_id'];
        unset($where['shop_id']);

        $list = $this->salesReportService->getSaleGroupBySkuList($where, $time, $product_ids);

        return $list->toJson();
    }

    public function saleGroupByOrderList()
    {
        $condition = $this->searchCondition();
        $where = $condition[0];
        $time = $condition[1];

        $where['channel'] = 'shop';
        $where['channel_id'] = $where['shop_id'];
        $where['status'] = Order::STATUS_PAY;
        unset($where['shop_id']);

        $list = $this->salesReportService->getSaleGroupByOrderList($where, $time);

        return $list->toJson();
    }

    public function saleGroupByClientList()
    {
        $condition = $this->searchCondition();
        $where = $condition[0];
        $time = $condition[1];

        $where['channel_id'] = $where['shop_id'];
        $where['status'] = Order::STATUS_PAY;
        unset($where['shop_id']);

        $list = $this->salesReportService->getSaleGroupByClientList($where, $time);

        return $list->toJson();
    }

    public function saleGroupBySalerList()
    {
        $condition = $this->searchCondition();
        $where = $condition[0];
        $time = $condition[1];

        $list = $this->salesReportService->getSaleGroupBySalerList($where, $time);

        return $list->toJson();
    }

    public function saleGroupByComStoreList()
    {
        $condition = $this->searchCondition();
        $where = $condition[0];
        $time = $condition[1];

        $list = $this->salesReportService->getSaleGroupByComStoreList($where, $time);

        return $list->toJson();
    }

    public function searchCondition()
    {
        $where['shop_id'] = session('shop_id');
        $time = [];
        $beginTime = '';
        if (request('beginTime')) {
            $beginTime = date('Y-m-d', strtotime(request('beginTime'))) . ' 00:00:00';
        }

        $endTime = '';
        if (request('endTime')) {
            $endTime = date('Y-m-d', strtotime(request('endTime'))) . ' 23:59:59';
        }

        if (!empty(request('beginTime')) && !empty(request('endTime'))) {
            $where['created_at'] = ['<=', $endTime];
            $time['created_at'] = ['>=', $beginTime];
        }

        if (!empty(request('endTime'))) {
            $time['created_at'] = ['<=', $endTime];
        }

        if (!empty(request('beginTime'))) {
            $time['created_at'] = ['>=', $beginTime];
        }

        if (request('ordersSn')) {
            $where['order_no'] = ['like', '%' . request('ordersSn') . '%'];
        }

        $search_goods_ids = [];
        $g_is_search = false;
        $g_goods_ids = [];
        if (request('searchKey')) {
            $g_is_search = true;
            $goods = Goods::where('name', 'like', '%' . request('searchKey') . '%')->orWhere('goods_no', 'like', '%' . request('searchKey') . '%')->get();
            if ($goods && $goods->count() > 0) {
                $g_goods_ids = $goods->pluck('id')->toArray();
                $g_goods_ids = array_unique($g_goods_ids);
                sort($g_goods_ids);
            }
        }

        $search_goods_ids[] = ['goods_ids' => $g_goods_ids, 'is_search' => $g_is_search];
        $brand_search = false;
        $brand_goods_ids = [];
        if (request('blandId')) {
            $brand_search = true;
            $goodsList = Goods::where('brand_id', request('blandId'))->get();
            if ($goodsList && $goodsList->count() > 0) {
                $brand_goods_ids = $goodsList->pluck('id')->toArray();
                sort($brand_goods_ids);
            }
        }

        $search_goods_ids[] = ['goods_ids' => $brand_goods_ids, 'is_search' => $brand_search];
        $style_search = false;
        $style_goods_ids = [];
        if (request('styleId')) {
            $style_search = true;
            $goodsList = Goods::where('style_id', request('styleId'))->get();
            if ($goodsList && $goodsList->count() > 0) {
                $style_goods_ids = $goodsList->pluck('id')->toArray();
                sort($style_goods_ids);
            }
        }

        $search_goods_ids[] = ['goods_ids' => $style_goods_ids, 'is_search' => $style_search];
        $year_search = false;
        $year_goods_ids = [];
        if (request('year')) {
            $year_search = true;
            $goodsList = Goods::where('year', request('year'))->get();
            if ($goodsList && $goodsList->count() > 0) {
                $year_goods_ids = $goodsList->pluck('id')->toArray();
                sort($year_goods_ids);
            }
        }

        $search_goods_ids[] = ['goods_ids' => $year_goods_ids, 'is_search' => $year_search];
        $season_search = false;
        $season_goods_ids = false;
        if (request('seasonId')) {
            $season_search = true;
            $goodsList = Goods::where('season_id', request('seasonId'))->get();
            if ($goodsList && $goodsList->count() > 0) {
                $season_goods_ids = $goodsList->pluck('id')->toArray();
                sort($season_goods_ids);
            }
        }

        $search_goods_ids[] = ['goods_ids' => $season_goods_ids, 'is_search' => $season_search];
        $a_is_search = false;
        $a_goods_ids = [];
        if (request('searchKey')) {
            $a_is_search = true;
            $goods = Goods::where('name', 'like', '%' . request('searchKey') . '%')->orWhere('goods_no', 'like', '%' . request('searchKey') . '%')->get();
            if ($goods && $goods->count() > 0) {
                $a_goods_ids = $goods->pluck('id')->toArray();
                $a_goods_ids = array_unique($a_goods_ids);
                sort($a_goods_ids);
            }
        }

        $search_goods_ids[] = ['goods_ids' => $a_goods_ids, 'is_search' => $a_is_search];
        $b_is_search = false;
        $b_goods_ids = [];
        if (request('categoryId')) {
            $b_is_search = true;
            $category_goods = GoodsCategory::where('category_id', request('categoryId'))->get();
            if ($category_goods && $category_goods->count() > 0) {
                $b_goods_ids = $category_goods->pluck('goods_id')->toArray();
                $b_goods_ids = array_unique($b_goods_ids);
                sort($b_goods_ids);
            }
        }

        $search_goods_ids[] = ['goods_ids' => $b_goods_ids, 'is_search' => $b_is_search];
        $spec_goods_ids = [];
        $c_is_search = false;
        $tmpGoodsProduct = GoodsProduct::where('is_show', 1)->first();
        $tmpSpec = SpecsValue::find($tmpGoodsProduct->specID[0]);
        if ($tmpSpec->spec_id == 1) {
            $left_type = 'size';
        } elseif ($tmpSpec->spec_id == 2) {
            $left_type = 'color';
        }

        $product_ids = [];
        if (request('colorId') && !request('sizeId')) {
            $c_is_search = true;
            $like = $left_type == 'color' ? '["' . request('colorId') . '"%' : '%"' . request('colorId') . '"]';
            $products = GoodsProduct::where('is_show', 1)->where('specID', 'like', $like)->get();
            if ($products && $products->count() > 0) {
                $spec_goods_ids = $products->pluck('goods_id')->toArray();
                $product_ids = $products->pluck('id')->toArray();
            }
        } elseif (!request('colorId') && request('sizeId')) {
            $c_is_search = true;
            $like = $left_type == 'size' ? '["' . request('sizeId') . '"%' : '%"' . request('sizeId') . '"]';
            $products = GoodsProduct::where('is_show', 1)->where('specID', 'like', $like)->get();
            if ($products && $products->count() > 0) {
                $spec_goods_ids = $products->pluck('goods_id')->toArray();
                $product_ids = $products->pluck('id')->toArray();
            }
        } elseif (request('colorId') && request('sizeId')) {
            $c_is_search = true;
            $like = $left_type == 'color' ? '["' . request('colorId') . '","' . request('sizeId') . '"]' : '["' . request('sizeId') . '","' . request('colorId') . '"]';
            $products = GoodsProduct::where('is_show', 1)->where('specID', $like)->get();
            if ($products && $products->count() > 0) {
                $spec_goods_ids = $products->pluck('goods_id')->toArray();
                $product_ids = $products->pluck('id')->toArray();
            }
        }

        if (!empty($spec_goods_ids)) {
            $spec_goods_ids = array_unique($spec_goods_ids);
            sort($spec_goods_ids);
        }

        $search_goods_ids[] = ['goods_ids' => $spec_goods_ids, 'is_search' => $c_is_search];
        $goods_ids = [];
        if (!empty($search_goods_ids)) {
            $collect_goods = collect($search_goods_ids);
            $filter_false_search = $collect_goods->filter(function ($item) {
                return $item['is_search'] === false;
            });

            if ($filter_false_search->count() != $collect_goods->count()) {
                $filter_empty_goods = $collect_goods->filter(function ($item) {
                    return $item['is_search'] && empty($item['goods_ids']);
                });

                if ($filter_empty_goods->count() <= 0) {
                    $filter_goods = $collect_goods->filter(function ($item) {
                        return $item['is_search'] && !empty($item['goods_ids']);
                    });

                    if ($filter_goods->count() > 0) {
                        $filter_goods = array_column($filter_goods->values()->toArray(), 'goods_ids');
                        $tmp = [];
                        $tmp_count = 0;
                        foreach ($filter_goods as $value) {
                            if (empty($tmp) && $tmp_count == 0) {
                                $tmp = $value;
                            } else {
                                $tmp = array_intersect($tmp, $value);
                            }

                            $tmp_count++;
                        }

                        if (!empty($tmp)) {
                            $goods_ids = $tmp;
                        } else {
                            $goods_ids = [0];
                        }
                    }
                } else {
                    $goods_ids = [0];
                }
            }
        }

        return [$where, $time, $goods_ids, $product_ids];
    }

    public function saleDetailListSum()
    {
        $condition = $this->searchCondition();
        $where = $condition[0];
        $time = $condition[1];
        $goods_ids = $condition[2];
        $product_ids = $condition[3];

        $dataListType = request('dataListType');
        $avgGrossProfitRate = 0;
        $sumGrossProfit = 0;
        $sumQuantity = 0;
        $sumTrueAmount = 0;
        $type = 'statistics';
        switch ($dataListType) {
            case  'saleRetailList' :
                if ($goods_ids === [0]) {
                    $product_ids = [0];
                } elseif (!empty($goods_ids) && $goods_ids !== [0]) {
                    $tmp_ids = GoodsProduct::whereIn('goods_id', $goods_ids)->pluck('id')->all();
                    if (!empty($product_ids)) {
                        $product_ids = array_intersect($product_ids, $tmp_ids);
                    } else {
                        $product_ids = $tmp_ids;
                    }
                }

                $where['channel_id'] = $where['shop_id'];
                unset($where['shop_id']);

                $list = $this->salesReportService->getSaleDetailList($where, $time, $product_ids, 0);
                $sumQuantity = $list->sum('quantity');
                $sumTrueAmount = $list->sum('total');

                $cost_total = $list->sum('costTotal');
                $sumGrossProfit = $sumTrueAmount - $cost_total;
                $avgGrossProfitRate = $sumTrueAmount == 0 ? 0 : number_format(($sumGrossProfit / $sumTrueAmount) * 100, 2, ".", "");


                break;
            case  'groupBySkuList' :
                if ($goods_ids === [0]) {
                    $product_ids = [0];
                } elseif (!empty($goods_ids) && $goods_ids !== [0]) {
                    $tmp_ids = GoodsProduct::whereIn('goods_id', $goods_ids)->pluck('id')->all();
                    if (!empty($product_ids)) {
                        $product_ids = array_intersect($product_ids, $tmp_ids);
                    } else {
                        $product_ids = $tmp_ids;
                    }
                }

                $where['channel_id'] = $where['shop_id'];
                unset($where['shop_id']);

                $list = $this->salesReportService->getSaleGroupBySkuList($where, $time, $product_ids, 0);
                $sumQuantity = $list->sum('total_quantity');
                $sumTrueAmount = $list->sum('total_amount') / 100;

                $cost_total = $list->sum('costTotal');
                $sumGrossProfit = $sumTrueAmount - $cost_total;
                $avgGrossProfitRate = $sumTrueAmount == 0 ? 0 : number_format(($sumGrossProfit / $sumTrueAmount) * 100, 2, ".", "");
                break;
            case  'groupByOrderList' :
                $where['channel_id'] = $where['shop_id'];
                $where['status'] = Order::STATUS_PAY;
                unset($where['shop_id']);

                $list = $this->salesReportService->getSaleGroupByOrderList($where, $time, 0);
                $sumQuantity = $list->sum('count');
                $sumTrueAmount = $list->sum('total') / 100;

                $cost_total = $list->sum('costTotal');
                $sumGrossProfit = $sumTrueAmount - $cost_total;
                $avgGrossProfitRate = $sumTrueAmount == 0 ? 0 : number_format(($sumGrossProfit / $sumTrueAmount) * 100, 2, ".", "");

                break;
            case  'groupByClientList' :
                $where['channel_id'] = $where['shop_id'];
                $where['status'] = Order::STATUS_PAY;
                unset($where['shop_id']);

                $list = $this->salesReportService->getSaleGroupByClientList($where, $time, 0);
                $sumQuantity = $list->sum('total_count');
                $sumTrueAmount = $list->sum('total_amount') / 100;
                $cost_total = $list->sum('costTotal');
                $sumGrossProfit = $sumTrueAmount - $cost_total;
                $avgGrossProfitRate = $sumTrueAmount == 0 ? 0 : number_format(($sumGrossProfit / $sumTrueAmount) * 100, 2, ".", "");
                break;
            case  'groupBySalerList' :
                $list = $this->salesReportService->getSaleGroupBySalerList($where, $time, 0);

                $sumQuantity = $list->sum('quantity');
                $sumTrueAmount = $list->sum('trueAmount');
                $cost_total = $list->sum('costTotal');
                $sumGrossProfit = $sumTrueAmount - $cost_total;
                $avgGrossProfitRate = $sumTrueAmount == 0 ? 0 : number_format(($sumGrossProfit / $sumTrueAmount) * 100, 2, ".", "");

                break;
            case  'groupBySalerComStoreList' :
                $list = $this->salesReportService->getSaleGroupByComStoreList($where, $time, 0, $type);
                $order_ids = ShopOrder::whereIn('shop_id', $list->pluck('shop_id')->all())->pluck('order_id')->all();
                $sumQuantity = Order::whereIn('id', $order_ids)->sum('count');
                $total = Order::whereIn('id', $order_ids)->sum('total');
                $sumTrueAmount = $total / 100;
                break;
        }

        return response()->json([
            'avgGrossProfitRate' => $avgGrossProfitRate,
            'sumGrossProfit' => $sumGrossProfit,
            'sumQuantity' => $sumQuantity,
            'sumTrueAmount' => $sumTrueAmount,
        ]);
    }

    public function saleDetailListExcel()
    {
        $condition = $this->searchCondition();
        $where = $condition[0];
        $time = $condition[1];
        $goods_ids = $condition[2];
        $product_ids = $condition[3];

        $dataListType = request('dataListType');
        $prefix = '';
        $data = [];
        switch ($dataListType) {
            case  'saleRetailList' :
                if ($goods_ids === [0]) {
                    $product_ids = [0];
                } elseif (!empty($goods_ids) && $goods_ids !== [0]) {
                    $tmp_ids = GoodsProduct::whereIn('goods_id', $goods_ids)->pluck('id')->all();
                    if (!empty($product_ids)) {
                        $product_ids = array_intersect($product_ids, $tmp_ids);
                    } else {
                        $product_ids = $tmp_ids;
                    }
                }

                $where['channel_id'] = $where['shop_id'];
                unset($where['shop_id']);

                $list = $this->salesReportService->getSaleDetailList($where, $time, $product_ids);
                $prefix = '销售明细报表_';
                $data = $this->salesReportService->getSaleDetailListExportData($list);
                break;
            case  'groupBySkuList' :
                if ($goods_ids === [0]) {
                    $product_ids = [0];
                } elseif (!empty($goods_ids) && $goods_ids !== [0]) {
                    $tmp_ids = GoodsProduct::whereIn('goods_id', $goods_ids)->pluck('id')->all();
                    if (!empty($product_ids)) {
                        $product_ids = array_intersect($product_ids, $tmp_ids);
                    } else {
                        $product_ids = $tmp_ids;
                    }
                }

                $where['channel_id'] = $where['shop_id'];
                unset($where['shop_id']);

                $list = $this->salesReportService->getSaleGroupBySkuList($where, $time, $product_ids);
                $prefix = '按单品汇总_';
                $data = $this->salesReportService->getSaleGroupBySkuListData($list);
                break;
            case  'groupByOrderList' :
                $where['channel_id'] = $where['shop_id'];
                $where['status'] = Order::STATUS_PAY;
                unset($where['shop_id']);

                $list = $this->salesReportService->getSaleGroupByOrderList($where, $time);
                $prefix = '按订单汇总_';
                $data = $this->salesReportService->getSaleGroupByOrderListData($list);
                break;
            case  'groupByClientList' :
                $where['channel_id'] = $where['shop_id'];
                $where['status'] = Order::STATUS_PAY;
                unset($where['shop_id']);

                $list = $this->salesReportService->getSaleGroupByClientList($where, $time);
                $prefix = '按客户汇总_';
                $data = $this->salesReportService->getSaleGroupByClientListData($list);
                break;
            case  'groupBySalerList' :
                $list = $this->salesReportService->getSaleGroupBySalerList($where, $time);
                $prefix = '按销售员汇总_';
                $data = $this->salesReportService->getSaleGroupBySalerListData($list);
                break;
            case  'groupBySalerComStoreList' :
                $list = $this->salesReportService->getSaleGroupByComStoreList($where, $time);
                $prefix = '按销售员所属门店汇总_';
                $data = $this->salesReportService->getSaleGroupByComStoreListData($list);
                break;
        }

        $page = request('page') ? request('page') : 1;
        $limit = request('limit') ? request('limit') : 20;
        $type = request('type');
        $lastPage = $list->lastPage();
        if ($page == 1) {
            session(['export_sales_list_cache_' . $dataListType => generate_export_cache_name('export_sales_list_cache_' . $dataListType . '_')]);
        }

        $cacheName = session('export_sales_list_cache_' . $dataListType);
        if ($this->cache->has($cacheName)) {
            $cacheData = $this->cache->get($cacheName);
            $this->cache->put($cacheName, array_merge($cacheData, $data), 300);
        } else {
            $this->cache->put($cacheName, $data, 300);
        }

        if ($page == $lastPage) {
            $title = [];
            switch ($dataListType) {
                case 'saleRetailList':
                    $title = $this->salesReportService->getSaleDetailListExportTitle();
                    break;
                case 'groupBySkuList':
                    $title = $this->salesReportService->getSaleGroupBySkuListTitle();
                    break;
                case 'groupByOrderList':
                    $title = $this->salesReportService->getSaleGroupByOrderListTitle();
                    break;
                case 'groupByClientList':
                    $title = $this->salesReportService->getSaleGroupByClientListTitle();
                    break;
                case 'groupBySalerList':
                    $title = $this->salesReportService->getSaleGroupBySalerListTitle();
                    break;
                case 'groupBySalerComStoreList':
                    $title = $this->salesReportService->getSaleGroupByComStoreListTitle();
                    break;
            }

            return $this->ajaxJson(true, ['status' => 'done', 'url' => '', 'type' => $type, 'title' => $title, 'cache' => $cacheName, 'prefix' => $prefix]);
        } else {
            $url_bit = route('admin.shop.report.sales.saleDetailListExcel', array_merge(['page' => $page + 1, 'limit' => $limit], request()->except('page', 'limit')));

            return $this->ajaxJson(true, ['status' => 'goon', 'url' => $url_bit, 'page' => $page, 'totalPage' => $lastPage]);
        }
    }
}